home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_10_01
/
cmenu.exe
/
CMENU1.C
< prev
next >
Wrap
Text File
|
1991-10-17
|
10KB
|
447 lines
/************************************************************
* Program: CMENU Menu Compiler
* Module: cmenu1.c
* Menu Compiler:
* Main and Utility Functions
* Written by: Leor Zolman, 7/91
************************************************************/
#define MASTER
#include "cmenu.h"
#include "ccmenu.h"
#include <string.h>
#if __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif
int main(argc,argv)
int argc;
char **argv;
{
register i;
printf("CMENU Menu Compiler v%s\n", VERSION);
if (argc < 2)
{
puts("usage: cmenu <menu-source-file(s)>\n");
return 0;
}
for (i = 1; i < argc; i++)
if (dofile(argv[i]) == ERROR) /* process source files */
return 1;
return 0;
}
/************************************************************
* dofile():
* Process a single .mnu source file
************************************************************/
int dofile(name)
char *name;
{
register i;
char *cp;
if ((cp = strstr(name, ".mnu")) ||
(cp = strstr(name, ".MNU")))
*cp = '\0';
strcpy(src_name, name);
strcat(src_name, ".mnu");
strcpy(obj_name, name);
if ((fp = fopen(src_name, "r")) == NULL)
return fprintf(stderr, "Can't open %s\n", src_name);
n_menus = 0;
lineno = 1;
in_menu = FALSE;
fatal = FALSE;
/* Main processing loop. Read a token and process it,
* until end of file is reached:
*/
while ((token = gettok(fp)) != T_EOF)
{
if (!in_menu && token != T_MENU)
{
error("Each menu must begin with the Menu keyword");
break;
}
if ((*keywords[token].t_func)() == ERROR)
if (fatal) /* If fatal error, exit loop */
break;
}
fclose(fp);
if (!n_menus)
return error("No menus defined");
if (in_menu)
{
if (n_items)
itemcheck();
error("Menu definition missing \"Endmenu\" statement");
}
for (i = 0; i < n_menus; i++) /* check for undefined */
if (!MInfo[i].Processed) /* "lmenu" references */
{
printf("Local Menu \"%s\" is undefined.\n",
MInfo[i].Name);
err_flag = TRUE;
}
if (err_flag)
return ERROR;
if (write_file() == ERROR)
return ERROR;
return OK;
}
/************************************************************
* create_menu():
* Construct a new menu information structure and
* return it (by value).
* Set fatal to TRUE if can't create.
************************************************************/
MINFO create_menu(name)
char *name;
{
MINFO mi;
if (n_menus == MAX_MENUS)
fatalerr("Maximum # of menus (%d) exceeded", MAX_MENUS);
else
{
strcpy(mi.Name, name);
mi.Processed = FALSE;
}
return mi;
}
/************************************************************
* find_menu():
* Search the Menu Info table for a named local menu.
* If found:
* Return a pointer to the entry if found, and set
* global variable menu_num to the menu's index
* else:
* return NULL
************************************************************/
MINFO *find_menu(name)
char *name;
{
int i;
for (i = 0; i < n_menus; i++)
if (!strcmp(MInfo[i].Name, name))
{
menu_num = i;
return &MInfo[i];
}
return NULL;
}
/************************************************************
* create_item(): Allocate space for Item Info structure,
* Initialize it and return a pointer to the structure
* Return NULL if there was a creation error.
************************************************************/
IINFO *create_item(name)
char *name;
{
IINFO *IIp;
ITEM *Ip;
if (n_items == MAX_ITEMS)
{
fatalerr("Max. # of items (%d) exceeded", MAX_ITEMS);
return NULL;
}
if ((IIp = (IINFO *) malloc(sizeof(IINFO))) == NULL)
{
fatalerr("Out of memory");
return NULL;
}
strcpy(IIp->Name, name);
Ip = &IIp->Item;
Ip->acttyp = ACT_NONE;
Ip->pre_clear = Ip->post_clear = Ip->prompt = DEFAULT;
Ip->nextcode = DEFAULT;
Ip->nextitem = Ip->lmenunum = 0;
*Ip->text = *Ip->path = *Ip->action = *Ip->help = '\0';
return IIp;
}
/************************************************************
* find_item():
* Search the Item Info table for a named item in the
* currently active menu definition.
* If item name found:
* Set item_num to the index value of the Item,
* Return a pointer to the entry
* else:
* return NULL
************************************************************/
IINFO *find_item(name)
char *name;
{
int i;
for (i = 0; i < n_items; i++)
if (!strcmp(MIp->Items[i]->Name, name))
{
item_num = i;
return MIp->Items[i];
}
return NULL;
}
/************************************************************
* itemcheck():
* Check the currently active item to make sure
* both a Text and an Action clause have been
* explicitly given.
************************************************************/
Void itemcheck()
{
if (!*Ip->text)
error("No TEXT clause found for current item");
if (Ip->acttyp == ACT_NONE)
error("No ACTION clause found for current item");
}
/************************************************************
* write_file():
* Write menu object file to disk, ready for
* execution via rmenu.
* Menu object file format:
* --------------------------------
* <count> (integer count of # of menus in file)
* MENU 1 (MENU structure for 1st Menu)
* ITEM 1
* ITEM 2
* ...
* ITEM n_items
* MENU 2 (MENU structure for 2nd Menu)
* ...
* .
* .
* .
* MENU <count> (MENU structure for final Menu)
* ...
* --------------------------------
*
************************************************************/
int write_file()
{
int i,j;
strcat(obj_name, ".mnc");
if ((fp = fopen(obj_name, "wb")) == NULL)
{
fprintf(stderr,
"Cannot open %s for writing.\n", obj_name);
return ERROR;
}
if (fwrite((Void *)&n_menus, sizeof n_menus, 1, fp) != 1)
{
fprintf(stderr,
"Error writing menu count to %s\n", obj_name);
return ERROR;
}
for (i = 0; i < n_menus; i++)
{
Mp = &MInfo[i].Menu;
if (fwrite((Void *) Mp, sizeof (MENU), 1, fp) != 1)
{
fprintf(stderr,
"Error writing to %s\n", obj_name);
return ERROR;
}
for (j = 0; j < Mp->nitems; j++)
{
if (fwrite((Void *) &MInfo[i].Items[j]->Item,
sizeof (ITEM), 1, fp) != 1)
{
fprintf(stderr,
"Error writing to %s\n", obj_name);
return ERROR;
}
free(MInfo[i].Items[j]);
}
}
printf("Menu object file %s written.\n", obj_name);
return OK;
}
/************************************************************
* warning():
* Display a warning message, preceded by source
* file name and line number, supporting format
* conversions.
************************************************************/
#if __STDC__
int warning(char *text, ...)
#else
int warning(text)
char *text;
#endif
{
char **textp = &text;
fprintf(stderr, "%s (%d): ", src_name, lineno);
fprintf(stderr, text, *++textp, *++textp);
fprintf(stderr, "\n");
return OK;
}
/************************************************************
* error():
* Display an error message, preceded by source
* file name and line number, supporting format
* conversions.
************************************************************/
#if __STDC__ /* ANSI variable-#-of-args method: */
int error(char *fmt, ...)
{
va_list arglist;
va_start(arglist, fmt);
#else /* old "varargs" method: */
int error(fmt, va_alist)
char *fmt;
va_dcl
{
va_list arglist;
va_start(arglist);
#endif
/* the rest is the same, ANSI or varargs: */
fprintf(stderr, "%s (%d): ", src_name, lineno);
vfprintf(stderr, fmt, arglist);
va_end(arglist);
fprintf(stderr, "\n");
err_flag = TRUE;
return ERROR;
}
/************************************************************
* fatalerr():
* Like error, except global flag "fatal" is set.
************************************************************/
#if __STDC__ /* start function the ANSI way... */
int fatalerr(char *fmt, ...)
{